﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using GeoRef;

namespace GeoRef
{
    [TestFixture]
    public class GeoRouteWhiteBoxTests
    {
        GeoRoute route, r;
        GeoLoc begin;
        GeoLoc end;

        /// <summary>
        /// Tries to create a new GeoRoute object with start
        /// point equal to end point. It should catch an
        /// ArgumentException exception
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentException))]
        public void TestCostr1() {
            begin = new GeoLoc(43.641504, 10.390496, "Pisa", "" );
            end = new GeoLoc(43.641504, 10.390496, "Pisa", "" );
            r = new GeoRoute(begin, end);
        }

        /// <summary>
        /// Creates a valid route
        /// </summary>
        [SetUp]
        public void Init() {
            begin = new GeoLoc(43.641504, 10.390496, "Pisa", "");
            end = new GeoLoc(43.591454, 10.390496, "Pisa", "");
            route = new GeoRoute(begin, end);
        }

        /// <summary>
        /// Tests "set" of Start and End property
        /// </summary>
        [Test]
        public void TestSetStartEnd() {
            Console.WriteLine("Right example of route");
            route.Start = new GeoLoc(43.782215, 11.25431, "Firenze", "");
            route.End = new GeoLoc(43.046524, 12.430863, "Perugia", "");
            Assert.AreEqual(route.Start, new GeoLoc(43.782215, 11.25431, "Firenze", ""));
            Assert.AreEqual(route.End, new GeoLoc(43.046524, 12.430863, "Perugia", ""));
            Console.WriteLine("Route: \nStart:" + (route.Start).ToString()+"\nEnd: " +(route.End).ToString());
        }

        /// <summary>
        /// Tests "set" method of Start property, forcing it
        /// value to the same of End Point. It should catch an
        /// ArgumentException exception.
        /// </summary>
        [Test, ExpectedException (typeof(ArgumentException))]
        public void TestSetStart() {
            route.Start = route.End;
            Console.WriteLine("Impossibile have same start and end points");
        }

        /// <summary>
        /// Tests "set" method of End property, forcing it
        /// value to the same of Start Point. It should catch an
        /// ArgumentException exception.
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentException))]
        public void TestSetEnd() {
            route.End = route.Start;
            Console.WriteLine("Impossibile to have same start and end points");
        }

        /// <summary>
        /// Tests "get" of Distance and DistanceInMiles properties
        /// </summary>
        [Test]
        public void TestDistance() {
            Assert.IsNotNull(route.Distance);
            Console.WriteLine("Distance km " + route.Distance);
            Assert.IsNotNull(route.DistanceInMiles);
            Console.WriteLine("Distance mi " + route.DistanceInMiles);
        }

        /// <summary>
        /// Tests "get" of Time property
        /// </summary>
        [Test]
        public void TestTime() {
            Assert.IsNotNull(route.Time);
            Console.WriteLine("Time in minutes " + route.Time);
        }

        /// <summary>
        /// Tests set and get of passengers property, including
        /// exception in case of negative value
        /// </summary>
        [Test, ExpectedException(typeof(FormatException))]
        public void TestPassengers() {
            Assert.IsNotNull(route.Passengers);
            route.Passengers = 2;
            Assert.AreEqual(route.Passengers, 2);
            route.Passengers = -2;
        }

        /// <summary>
        /// Tests insertion of a new viaPoint at the end of the actual list
        /// </summary>
        [Test]
        public void TestInsertViaPoint1() {
            GeoLoc p1 = new GeoLoc(43.666332, 10.638223, "Pontedera, Italy", "");
            route.InsertViaPoint(p1);
            List<GeoLoc> vPoints = route.ViaPoints;
            Assert.AreEqual(vPoints.Last(), p1);
        }

        /// <summary>
        /// Tests insertion of a new viaPoint before a specified existing viaPoint
        /// </summary>
        [Test]
        public void TestInsertViaPoint2() {
            GeoLoc p1 = new GeoLoc(43.68715, 10.484845, "Navacchio, Italy", "");
            GeoLoc p2 = new GeoLoc(43.666332, 10.638223, "Pontedera, Italy", "");
            route.InsertViaPoint(p1);
            route.InsertViaPoint(p2, p1);
            List<GeoLoc> vPoints = route.ViaPoints;
            Assert.AreEqual(vPoints.First(), p2);
            Assert.AreEqual(vPoints.Last(), p1);
        }

        /// <summary>
        /// Tests insertion of a new viaPoint before a specified index of the list
        /// </summary>
        [Test]
        public void TestInsertViaPoint3() {
            GeoLoc p1 = new GeoLoc(43.68715, 10.484845, "Navacchio, Italy", "");
            GeoLoc p2 = new GeoLoc(43.666332, 10.638223, "Pontedera, Italy", "");
            route.InsertViaPoint(p1);
            route.InsertViaPoint(p2, 0);
            List<GeoLoc> vPoints = route.ViaPoints;
            Assert.AreEqual(vPoints.First(), p2);
            Assert.AreEqual(vPoints.Last(), p1);
        }

        /// <summary>
        /// Tests insertion of a new viaPoint before a non-existent index
        /// of the list; it should catch an ArgumentOutOfRangeException
        /// exception.
        /// </summary>
        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void TestInstertViaPoint4() {
            GeoLoc p1 = new GeoLoc(43.666332, 10.638223, "Pontedera, Italy", "");
            route.InsertViaPoint(p1, 4);
        }

        /// <summary>
        /// Tests GeoRoute.RemoveViaPoint() method, first inserting a 
        /// new viaPoint in the list, then deleting it
        /// </summary>
        [Test]
        public void TestRemoveViaPoint() {
            GeoLoc p1 = new GeoLoc(43.666332, 10.638223, "Pontedera, Italy", "");
            route.InsertViaPoint(p1);
            List<GeoLoc> vPoints = route.ViaPoints;
            Assert.AreNotEqual(vPoints.FindIndex(delegate(GeoLoc l) { return (l == p1); }), -1);
            route.RemoveViaPoint(p1);
            Assert.AreEqual(vPoints.FindIndex(delegate(GeoLoc l) { return (l == p1); }), -1);
        }

        /// <summary>
        /// Tests GeoRoute.ClearViaPoints() method, first inserting two
        /// new viaPoints and checking the number of elements in the list,
        /// then calling the method and checking if the list is void.
        /// </summary>
        [Test]
        public void TestClearViaPoint() {
            route.ClearViaPoints();
            GeoLoc p1 = new GeoLoc(43.68715, 10.484845, "Navacchio, Italy", "");
            GeoLoc p2 = new GeoLoc(43.666332, 10.638223, "Pontedera, Italy", "");
            route.InsertViaPoint(p1);
            route.InsertViaPoint(p2);
            List<GeoLoc> vPoints = route.ViaPoints;
            Assert.AreEqual(vPoints.Count(), 2);
            route.ClearViaPoints();
            Assert.AreEqual(vPoints.Count(), 0);
        }



    }
}
